package com.neusoft.codegen.codegen.service;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.neusoft.codegen.codegen.CodegenConstant;
import com.neusoft.codegen.codegen.entity.HeaColumn;
import com.neusoft.codegen.codegen.entity.HeaTable;
import com.neusoft.codegen.codegen.entity.MyEntity;
import com.neusoft.codegen.codegen.entity.MyField;
import com.neusoft.codegen.codegen.utils.DateUtils;
import com.neusoft.codegen.codegen.utils.FileUtils;
import com.neusoft.codegen.codegen.utils.OrmUtil;
import com.neusoft.codegen.codegen.utils.PropertiesUtil;
import com.neusoft.codegen.codegen.utils.freemarker.Freemarker;
import com.neusoft.codegen.codegen.utils.string.CStringUtils;
import com.vonchange.headb.core.map.HeaMap;
import com.vonchange.headb.utils.logger.HLogUtils;
import com.vonchange.headb.utils.map.HHashMap;

@Service
@Transactional
public class GenService {
	private static final Log logger = LogFactory.getLog(GenService.class);
	@Resource
	private HeaColumnService viewColumnService;
	@Resource
	private HeaTableService viewTableService;
	private boolean coveredEntity = false;

	public boolean isCoveredEntity() {
		return coveredEntity;
	}

	public void setCoveredEntity(boolean coveredEntity) {
		this.coveredEntity = coveredEntity;
	}

	private MyEntity toEntity(HeaMap parameter) {
		HeaTable viewTable = viewTableService.findViewTable(parameter);
		MyEntity myEntity = new MyEntity();
		myEntity.setEntityId(viewTable.getTableId());
		myEntity.setTableName(viewTable.getTableName());
		myEntity.setEntityName(OrmUtil.toEntity(viewTable.getTableName()));
		String entityComment = viewTable.getTableComment();
		if (!viewTable.getTableType().equalsIgnoreCase("VIEW") && (null == entityComment || CStringUtils.isBlank(entityComment))) {
			throw new RuntimeException(viewTable.getTableName() + "表请加入注释!");
		}
		if (entityComment.indexOf("_") != -1) {
			entityComment = CStringUtils.substringAfterLast(entityComment, "_");
		}
		entityComment = entityComment.replaceAll("表", "");
		myEntity.setEntityComment(entityComment);
		String entityType = null;
		if (viewTable.getTableType().equalsIgnoreCase("BASE TABLE")) {
			entityType = "base";
		}
		if (viewTable.getTableType().equalsIgnoreCase("VIEW")) {
			entityType = "view";
		}
		myEntity.setEntityType(entityType);
		myEntity.setViewTable(viewTable);
		return myEntity;
	}

	private List<MyField> toFields(HeaMap parameter, MyEntity myEntity) {
		List<HeaColumn> viewColumns = viewColumnService.findViewColumnList(parameter);
		List<MyField> myFileds = new ArrayList<MyField>();
		MyField myField;
		for (HeaColumn viewColumn : viewColumns) {
			myField = new MyField();
			myField.setFieldId(viewColumn.getColumnId());
			myField.setEntityId(viewColumn.getTableId());
			myField.setColumnName(viewColumn.getColumnName());
			myField.setColumnType(viewColumn.getColumnType());
			myField.setFieldName(OrmUtil.toFiled(viewColumn.getColumnName()));
			myField.setFieldNameCap(CStringUtils.capitalize(myField.getFieldName()));
			myField.setDefaultValue(viewColumn.getDefaultValue());
			myField.setLength(viewColumn.getMaxLength());
			myField.setPosition(viewColumn.getPosition());
			myField.setPrecision(viewColumn.getPrecision());
			myField.setScale(viewColumn.getScale());
			String fieldComment = viewColumn.getColumnComment();

			if (fieldComment.indexOf(":") != -1) {
				fieldComment = CStringUtils.substringBefore(fieldComment, ":").trim();
			}
			if (fieldComment.indexOf("(") != -1) {
				fieldComment = CStringUtils.substringBefore(fieldComment, "(").trim();
			}
			myField.setFieldComment(fieldComment);
			Boolean iskey = false;
			if (myEntity.getEntityType().equalsIgnoreCase("view")) {
				if (viewColumn.getPosition() == 1) {
					iskey = true;// 视图默认位置1为主键
				}
			}
			if ("PRI".equalsIgnoreCase(viewColumn.getColumnKey())) {
				iskey = true;
			}
			myField.setIskey(iskey);

			Boolean nullable = true;
			if (viewColumn.getNullable().equalsIgnoreCase("YES")) {
				nullable = false;
			}
			myField.setNullable(nullable);
			String type = "String";
			String typeInDb = viewColumn.getDataType();
			if (typeInDb.equalsIgnoreCase("varchar") || typeInDb.equalsIgnoreCase("char")) {
				type = "String";
			}
			if (typeInDb.equalsIgnoreCase("int") || typeInDb.equalsIgnoreCase("tinyint")|| typeInDb.equalsIgnoreCase("smallint")
					||typeInDb.equalsIgnoreCase("mediumint")) {
				type = "Integer";
			}
			if ("Integer".equals(type)) {
				String fieldName = myField.getFieldName();
				if (fieldName.endsWith("Id") || fieldName.endsWith("id")) {
					type = "Integer";
				}
			}
			if (typeInDb.equalsIgnoreCase("float")) {
				type = "Float";
			}
			if (typeInDb.equalsIgnoreCase("datetime") || typeInDb.equalsIgnoreCase("date") || typeInDb.equalsIgnoreCase("time")) {
				type = "Date";
				myEntity.setDateFlag(true);
			}
			if (typeInDb.equalsIgnoreCase("decimal")) {
				type = "BigDecimal";
				myEntity.setBigDecimalFlag(true);
			}
			if (typeInDb.equalsIgnoreCase("bit")) {
				type = "Boolean";
				if (!nullable) {
					type = "boolean";
				}
			}
			if (typeInDb.equalsIgnoreCase("bigint")) {
				type = "Long";
			}
			myField.setType(type);
			if (iskey) {
				myEntity.setIdType(type);
				myEntity.setIdName(myField.getFieldName());
			}
			//
			if (!myEntity.getEntityType().equalsIgnoreCase("view") && (null == fieldComment || CStringUtils.isBlank(fieldComment))) {
				//throw new RuntimeException(viewColumn.getColumnName() + "字段请加入注释!");
			}

			myField.setViewColumn(viewColumn);
			myFileds.add(myField);
		}
		return myFileds;
	}

	public MyEntity getMyEntity(HeaMap parameter) {
		MyEntity myEntity = new MyEntity();
		myEntity = toEntity(parameter);
		List<MyField> myFields = toFields(parameter, myEntity);
		myEntity.setFields(myFields);
		return myEntity;
	}

	/**
	 * TODO entityFlag true 实体将覆盖
	 * 
	 * @param falg
	 */
	public void gen() {
		// 获取配置
		File properties = FileUtils.getClassPath(CodegenConstant.JDBCPROPATH, "codegen.properties");
		PropertiesUtil propertiesUtil = new PropertiesUtil(properties);
		Map<String, Object> pro = propertiesUtil.loadProperties();
		Map<String, Object> proNew = new HHashMap<String, Object>();
		for (Entry<String, ?> entry : pro.entrySet()) {
			if (entry.getKey().startsWith("codegen")) {
				proNew.put(CStringUtils.substringAfter(entry.getKey(), "codegen."), entry.getValue());
			}
		}// 获得codegen属性
		String dbName = propertiesUtil.getValue("jdbc.db.name");

		MyEntity myEntity = getMyEntity(new HeaMap().set("tableName_eq", propertiesUtil.getValue("codegen.tableName")).setViewParam("dbName", dbName));
		String entityName = propertiesUtil.getValue("codegen.entityName");
		if (null != entityName && !StringUtils.isBlank(entityName)) {
			myEntity.setEntityName(entityName);
		}
		if (myEntity.getEntityType().equals("view")) {
			myEntity.setEntityComment(propertiesUtil.getValue("codegen.viewComment"));
		}
		Freemarker freemarker = new Freemarker();
		String now = DateUtils.format("yyyy年MM月dd日 HH:mm:ss ", new Date());
		HHashMap<String, Object> dataMap = new HHashMap<String, Object>().set("bean", myEntity).set("pro", proNew).set("now", now);
		File templateFolder = FileUtils.getClassPath(CodegenConstant.BASEPROPATH + ".codegen.template", "");

		String sourcePath = propertiesUtil.getValue("codegen.source");
		File entityFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.entityPath"), myEntity.getEntityName() + ".java");
		// 生成实体
		if (!entityFile.exists() || coveredEntity) {
			freemarker.generateBytemplate(dataMap, templateFolder, "entity.ftl", entityFile);
			logger.info(HLogUtils.format(myEntity.getEntityName(), "生成成功!!"));
		} else {
			logger.warn(HLogUtils.format(myEntity.getEntityName(), "已存在!!"));
		}
		// 生成Mapper
		File iMapperFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.basePath") + ".mappers", myEntity.getEntityName() + "Mapper.java");
		File mapperFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.basePath") + ".mappers", myEntity.getEntityName() + "Mapper.xml");
		if (!mapperFile.exists()) {
			freemarker.generateBytemplate(dataMap, templateFolder, "mapper.ftl", iMapperFile);
			freemarker.generateBytemplate(dataMap, templateFolder, "mapperxml.ftl", mapperFile);
			logger.info(HLogUtils.format(myEntity.getEntityName(), "mapper生成成功!!"));
		} else {
			logger.warn(HLogUtils.format(myEntity.getEntityName(), "mapper已存在!!"));
		}
		// 生成Dao
		File iDaoFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.basePath") + ".dao", "I" + myEntity.getEntityName() + "Dao.java");
		File daoFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.basePath") + ".dao.impl", myEntity.getEntityName() + "DaoImpl.java");
		if (!daoFile.exists()) {
			freemarker.generateBytemplate(dataMap, templateFolder, "dao.ftl", iDaoFile);
			freemarker.generateBytemplate(dataMap, templateFolder, "daoImpl.ftl", daoFile);
			logger.info(HLogUtils.format(myEntity.getEntityName(), "Dao生成成功!!"));
		} else {
			logger.warn(HLogUtils.format(myEntity.getEntityName(), "Dao已存在!!"));
		}
		// 生成Service
		File iServiceFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.basePath") + ".service", "I" + myEntity.getEntityName() + "Service.java");
		File serviceFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.basePath") + ".service.impl", myEntity.getEntityName() + "ServiceImpl.java");
		if (!iServiceFile.exists()) {
			freemarker.generateBytemplate(dataMap, templateFolder, "service.ftl", iServiceFile);
			freemarker.generateBytemplate(dataMap, templateFolder, "serviceImpl.ftl", serviceFile);
			logger.info(HLogUtils.format(myEntity.getEntityName(), "Service生成成功!!"));
		} else {
			logger.warn(HLogUtils.format(myEntity.getEntityName(), "Service已存在!!"));
		}
		// 生成Action
	
		File actionFile = FileUtils.getSrcPath(sourcePath, propertiesUtil.getValue("codegen.basePath") + ".controller", myEntity.getEntityName() + "Controller.java");
		if (!actionFile.exists()) {
			freemarker.generateBytemplate(dataMap, templateFolder, "action.ftl", actionFile);
			logger.info(HLogUtils.format(myEntity.getEntityName(), "action生成成功!!"));
		} else {
			logger.warn(HLogUtils.format(myEntity.getEntityName(), "action已存在!!"));
		}

	}
}
